#import "Ble2318otaPlugin.h"
#import <GRDFUSDK/GRDFUTool.h>
#import "UnzipFirmware.h"
#import <CommonCrypto/CommonDigest.h>
#import "BleData.h"


@implementation Ble2318otaPlugin{//蓝牙搜素/连接 文件生成47命令 解压文件 开始升级
    NSString *filePath;
    NSString *colorPath;
    NSString *firewareData;
    NSString *strIdentifier;
}
static FlutterMethodChannel* channel;



+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
//  FlutterMethodChannel* channel = [FlutterMethodChannel
//      methodChannelWithName:@"ble2318ota_plugin"
//            binaryMessenger:[registrar messenger]];
//  Ble2318otaPlugin* instance = [[Ble2318otaPlugin alloc] init];
//  [registrar addMethodCallDelegate:instance channel:channel];
    
    
    channel = [FlutterMethodChannel
       methodChannelWithName:@"ble2318ota_plugin"
             binaryMessenger:[registrar messenger]];
    Ble2318otaPlugin* instance = [[Ble2318otaPlugin alloc] init];
   [registrar addMethodCallDelegate:instance channel:channel];
}


- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
  if ([@"getPlatformVersion" isEqualToString:call.method]) {
    result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
  }else if([@"checkFiles" isEqualToString:call.method]){
      NSString *path = @"";
      path = [call.arguments objectForKey:@"binPath"];
      UnzipFirmware *unzipFiles = [[UnzipFirmware alloc] init];
      NSURL *url = [[NSURL alloc] initWithString:path];
      NSArray *firmwareFilesURL = [unzipFiles unzipFirmwareFiles:url];
      for (NSURL *url in firmwareFilesURL) {
          NSString *strPath = url.path;
          NSLog(@"strPaht:%@",strPath);
          if([[strPath lowercaseString] containsString:@"application.b"]){
              filePath = strPath;
          }
          if([[strPath lowercaseString] containsString:@"gr5515ota_sign"]){
              colorPath = strPath;
          }
      }
//      NSLog(@"test-文件路径外1: %@",filePath);
//      NSLog(@"test-文件路径外2: %@",colorPath);
      NSString *fileMd5 =  [self getFileMD5StrFromPath:filePath];
      NSFileHandle* fh = [NSFileHandle fileHandleForReadingAtPath:colorPath];
      NSData *md5Data = [NSMutableData dataWithData:[fh readDataToEndOfFile]];
//      NSLog(@"fileMd5: %@",fileMd5);
//      NSLog(@"md5Data: %@",md5Data);
      NSData *resultv = [self enterOTAModeWithFileMD5:fileMd5 signMD5:md5Data];
      result(resultv);
  } else if([@"startOta" isEqualToString:call.method]){
      [self searchDevice];
  }else if([@"initBlueTools" isEqualToString:call.method]){
      [self initBlueTool];
  }else if([@"stopScan" isEqualToString:call.method]){
      [self stopScan];
  }else {
    result(FlutterMethodNotImplemented);
  }
}


- (void) initBlueTool{
    [[NewBle sharedManager] SetUpCentralManager];
    [[BleData sharedManager] setBleDelegate];
    [GRDFUTool enableLog:YES];
    
}

- (void)sendMessage:(NSString *)message {
    if(channel){
        [channel invokeMethod:@"sendMessage" arguments:message];
    }
}

-(void)searchDevice{
    [self sendMessage:@"1"];
    [[BleData sharedManager] startScanningWithServices:nil deviceBlock:^(CBPeripheral * _Nonnull device, NSDictionary<NSString *,id> * _Nonnull advertisementData, NSNumber * _Nonnull RSSI) {
        NSString * strName = device.name;
//        NSLog(@"strDeviceName= %@",strName);//Goodix_DFU
        if (([strName rangeOfString:@"DFU28"].location !=NSNotFound||[strName rangeOfString:@"Goodix_DFU"].location!=NSNotFound)&&strName.length>0)
        {
            [self sendMessage:@"3"];
            [self stopScan];
            strIdentifier = device.identifier.UUIDString;
            [self startDFU];
//            NSLog(@"strIdentifier = %@",strIdentifier);
        }
    }];
}

-(void)stopScan{
    [self sendMessage:@"2"];
    [[BleData sharedManager] StopScan];
}



#pragma mark 获取文件的MD5
- (NSString *)getFileMD5StrFromPath:(NSString *)path
{
//    NSLog(@"test-文件路径:%@",path);
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if([fileManager fileExistsAtPath:path isDirectory:nil])
    {
    
        NSData *data = [NSData dataWithContentsOfFile:path];
        unsigned char digest[CC_MD5_DIGEST_LENGTH];
        
        CC_MD5( data.bytes, (CC_LONG)data.length, digest );
        
        NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
        
        for( int i = 0; i < CC_MD5_DIGEST_LENGTH; i++ )
        {
            [output appendFormat:@"%02x", digest[i]];
        }
        
        return output;
    }
    else
        return @"";
}


-(NSData *)enterOTAModeWithFileMD5:(NSString*)strFileMD5  signMD5:(NSData*)signMD5
{
    //18+64
   unsigned char b[82];
    b[0] = CMD_OTA_MODE;
    b[1] = 0;
    for (int i = 0; i<16; i++) {
       b[i+2] = (int)strtoul([[strFileMD5 substringWithRange:NSMakeRange(i*2, 2)] UTF8String], 0, 16);
      }
    Byte * bytes =  (Byte*)[signMD5 bytes];
    for (int i = 0;  i<signMD5.length; i++) {
        b[18+i] = bytes[i];
        NSLog(@" b[%d] = %02x", 18+i,b[18+i]);
    }
    NSData *bleData = [self SendData:b length:82 needCRC:NO];
    return bleData;
}


//合并47命令
- (NSData*)SendData:( unsigned char*)b length:(int)length needCRC:(BOOL)needCRC
{
    if(needCRC==YES){
        int sam = 0;
        for (int j = 0; j < length-1; j++)
        {
            sam += b[j];
        }
        b[length-1] = sam;
    }
    NSMutableData *data = [[NSMutableData alloc] initWithBytes:b length:length];
    return data;
    
}

//开始升级
-(void)startDFU{
    NSFileHandle* fh = [NSFileHandle fileHandleForReadingAtPath:filePath];
    firewareData = [NSMutableData dataWithData:[fh readDataToEndOfFile]];
    [self sendMessage:@"4"];
    [GRDFUTool upgradeWithCentralManager:[[BleData sharedManager] getCentralManager]  //CBCentralManager实例
                              identifier:strIdentifier   //目标设备的identifier
                            firmwareData:firewareData             //固件数据
                                   reset:YES                //拷贝完成后设备是否重启
                               overwrite:YES                //如果目标区域已有固件，是否覆盖原固件。
                                delegate:self
                               extraInfo:nil];
}


// 汇顶DFU回调
- (void)dfuTaskDidAbortForError:(int)errCode message:(nonnull NSString *)msg type:(GRDTaskType)type extraInfo:(nonnull NSDictionary *)extraInfo {
    NSLog(@">>>>>>>>>  dfuTaskDidAbortForError---%@---extraInfo:%@",msg,extraInfo);
//    if (GRDTaskTypeDFUMode == type){
//
//    }
    [self sendMessage:@"9"];
    [self startDFU];
}

- (void)dfuTaskDidCompleteWithType:(GRDTaskType)type extraInfo:(nonnull NSDictionary *)extraInfo {
    NSLog(@">>>>>>>>>  onDfuComplete");
    [self sendMessage:@"8"];
}

- (void)dfuTaskDidStartWithType:(GRDTaskType)type extraInfo:(nonnull NSDictionary *)extraInfo {
    NSLog(@">>>>>>>>>  onDfuStart");
    [self sendMessage:@"6"];
}

- (void)dfuTaskDidUpdateProgress:(float)percent type:(GRDTaskType)type extraInfo:(nonnull NSDictionary *)extraInfo progressType:(int)progressType {
//    NSLog(@"dfuTaskDidUpdateProgress:%@",);
    //此处需要注意!!!，当为FASTDFU升级的时候，progressType == 1 是擦除flash的进度。progressType == 0是升级过程的进度。
     NSLog(@">>>>>>>>>  onDfuUpdateProgress: %.1f", percent);
    [self sendMessage:[NSString stringWithFormat:@"7,%d",(int)percent]];
    
}

@end
